import { MessageType } from '@/config';
import { clsx, type ClassValue } from 'clsx';
import JSZip from 'jszip';
import { twMerge } from 'tailwind-merge';
import { uploadImage } from './meituxiuxiu';

export function cn(...inputs: ClassValue[]) {
  return twMerge(clsx(inputs));
}

export function loadIconImage(file: File, { iconSize = 128 } = {}): Promise<ImageData> {
  return new Promise(async (resolve, reject) => {
    // 创建一个Image对象
    const image = new Image();

    // 设置Image对象的源为文件对象
    image.src = URL.createObjectURL(file);

    // 当图像加载完成后，将其绘制到canvas上
    image.onload = function () {
      // 创建canvas元素
      const canvas = document.createElement('canvas');
      const ctx = canvas.getContext('2d');

      // 设置canvas的尺寸与图像尺寸相同
      canvas.width = iconSize;
      canvas.height = iconSize;

      const width = image.naturalWidth;
      const height = image.height;

      if (ctx) {
        // 将图像绘制到canvas上
        if (width > height) {
          const r = width / iconSize;
          ctx.drawImage(image, 0, (iconSize - height / r) / 2, iconSize, height / r); // 绘制原始图像
        } else {
          const r = height / iconSize;
          ctx.drawImage(image, (iconSize - width / r) / 2, 0, width / r, iconSize);
        }

        // 获取imageData
        const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);

        // 这里可以对imageData进行操作，例如处理图像数据

        // 清理：释放创建的URL对象
        URL.revokeObjectURL(image.src);

        // 返回imageData
        resolve(imageData);
      }
    };

    // 处理图像加载失败的情况
    image.onerror = function (err) {
      reject(err);
    };
  });
}

export function getRandomNumber(min: number, max: number) {
  const randomNumber = Math.random();
  const scaledRandomNumber = min + (max - min) * randomNumber;
  return scaledRandomNumber;
}

/**
 * 随机选取数组中的一个元素
 * @param array - 要随机选取的数组
 * @returns 数组中的一个随机元素，如果数组为空则返回 undefined
 */
export function getRandomElement<T>(array: T[]): T | undefined {
  if (array.length === 0) {
    return undefined;
  }
  const randomIndex = Math.floor(Math.random() * array.length);
  return array[randomIndex];
}

// 随机挑选数组中的 n 个元素
export function getRandomElements<T>(array: T[], n: number): T[] {
  if (!array || n <= 0) return [];
  const copy = [...array];
  const length = array.length;
  n = Math.min(n, length);
  for (let i = 0; i < n; i++) {
    const j = Math.floor(Math.random() * (length - i)) + i;
    [copy[i], copy[j]] = [copy[j], copy[i]];
  }
  return copy.slice(0, n);
}

export function waitEleRender(
  selector: string,
  timeout: number,
  interval = 200,
): Promise<Element | null> {
  return new Promise((resolve) => {
    let timer: number | undefined = undefined;
    const ele = document.querySelector(selector);
    if (ele) {
      resolve(ele);
      return;
    }
    timer = setInterval(() => {
      const ele = document.querySelector(selector);
      if (ele) {
        resolve(ele);
        clearInterval(timer);
      }
    }, interval) as unknown as number;

    setTimeout(() => {
      resolve(null);
      clearInterval(timer);
    }, timeout);
  });
}

export function waitEleRenderWithDocument(
  selector: string,
  timeout: number,
  interval = 200,
  document = window.document,
): Promise<Element | null> {
  return new Promise((resolve) => {
    let timer: number | undefined = undefined;
    const ele = document.querySelector(selector);
    if (ele) {
      resolve(ele);
      return;
    }
    timer = setInterval(() => {
      const ele = document.querySelector(selector);
      if (ele) {
        resolve(ele);
        clearInterval(timer);
      }
    }, interval) as unknown as number;

    setTimeout(() => {
      resolve(null);
      clearInterval(timer);
    }, timeout);
  });
}

export function observeWaitElement(
  selector: string,
  container: HTMLElement,
  timeout = 5000,
): Promise<Element | null> {
  return new Promise((resolve, reject) => {
    // 初次立即检查元素是否存在
    const initialElement = document.querySelector(selector);
    if (initialElement) {
      resolve(initialElement);
      return;
    }

    // 创建 MutationObserver 实例
    const observer = new MutationObserver((mutationsList) => {
      // console.log(mutationsList);
      const targetElement = document.querySelector(selector);

      // 筛选与目标元素相关的变化
      const relevantMutations = mutationsList.filter((mutation) => {
        return mutation.target === targetElement || mutation.target.contains(targetElement);
      });

      if (relevantMutations.length > 0 && targetElement) {
        resolve(targetElement);
        observer.disconnect(); // 单次触发后自动停止监听
      }
    });

    // 开始观察
    observer.observe(container, {
      subtree: true,
      childList: true,
    });

    setTimeout(() => {
      observer.disconnect();
      resolve(null);
    }, timeout);
  });
}

export function observeWaitElements(
  selector: string,
  container: HTMLElement,
  callback: (eles: NodeListOf<HTMLDivElement>) => void,
  timeout = 5000,
): void {
  // 初次立即检查元素是否存在
  const initialElements = document.querySelectorAll(selector) as NodeListOf<HTMLDivElement>;
  if (initialElements.length > 0) {
    callback(initialElements);
    return;
  }

  // 创建 MutationObserver 实例
  const observer = new MutationObserver((mutationsList) => {
    const targetElements = document.querySelectorAll(selector) as NodeListOf<HTMLDivElement>;

    if (targetElements.length > 0) {
      const targetElement = targetElements[0];
      // 筛选与目标元素相关的变化
      const relevantMutations = mutationsList.filter((mutation) => {
        return mutation.target === targetElement || mutation.target.contains(targetElement);
      });

      if (relevantMutations.length > 0 && targetElement) {
        callback(targetElements);
        observer.disconnect();
      }
    }
  });

  // 开始观察
  observer.observe(container, {
    subtree: true,
    childList: true,
  });

  setTimeout(() => {
    observer.disconnect();
  }, timeout);
}

function getEleByXPath(xPath: string) {
  try {
    const xPathResult = document.evaluate(
      xPath,
      document,
      null,
      XPathResult.FIRST_ORDERED_NODE_TYPE,
    );
    return xPathResult.singleNodeValue as Element;
  } catch (error) {
    console.log(error);
    return null;
  }
}

export function waitEleRenderByXPath(
  xPath: string,
  timeout: number,
  interval = 200,
): Promise<Element | null> {
  return new Promise((resolve) => {
    let timer: number | undefined = undefined;
    const ele = getEleByXPath(xPath);
    if (ele) {
      resolve(ele);
      return;
    }
    timer = setInterval(() => {
      const ele = getEleByXPath(xPath);
      if (ele) {
        resolve(ele);
        clearInterval(timer);
      }
    }, interval) as unknown as number;

    setTimeout(() => {
      resolve(null);
      clearInterval(timer);
    }, timeout);
  });
}

// 把字符串压缩为 application/zip 格式的 blob
export async function toZipBlob(data: string, fileName: string) {
  const zip = new JSZip();
  zip.file(fileName, data);
  const blob = await zip.generateAsync({ type: 'blob', mimeType: 'application/zip' });
  return blob;
}

// 提取文件名称中的名称部分
export function getFileName(fileName: string) {
  const name = fileName.split('.')[0];
  return name;
}

// 读取目录句柄下的所有文件句柄
export async function getAllFileHandleByDirectoryHandle(
  directoryHandle: FileSystemDirectoryHandle,
) {
  const fileSystemFileHandles: FileSystemFileHandle[] = [];
  for await (const fileHandle of directoryHandle.values()) {
    if (fileHandle.kind === 'file') {
      fileSystemFileHandles.push(fileHandle);
    }
  }
  return fileSystemFileHandles;
}

// 读取目录句柄下的所有目录句柄
export async function getAllFDirectoryHandleByDirectoryHandle(
  directoryHandle: FileSystemDirectoryHandle,
) {
  const fileSystemDirectoryHandles: FileSystemDirectoryHandle[] = [];
  for await (const fileSystemDirectoryHandle of directoryHandle.values()) {
    if (fileSystemDirectoryHandle.kind === 'directory') {
      fileSystemDirectoryHandles.push(fileSystemDirectoryHandle);
    }
  }
  return fileSystemDirectoryHandles;
}

// 获取一个文件对象对应的 dataUrl
export async function getDataUrl(blob: Blob): Promise<string> {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onload = () => {
      resolve(reader.result as string);
    };
    reader.onerror = reject;
    reader.readAsDataURL(blob);
  });
}

// 创建按钮
export function createButton(text: string, className: string) {
  const button = document.createElement('button');
  button.textContent = text;
  button.className = className;
  return button;
}

// 获取当前获取的 tab
export async function getCurrentTab() {
  const [tab] = await chrome.tabs.query({
    active: true,
    currentWindow: true,
  });
  return tab;
}
// 生成唯一的 key
export function generateRandomId() {
  return `id-${Date.now()}-${Math.floor(Math.random() * 10000)}`;
}

// 获取图像 blob 的大小信息
export async function getImageSize(blob: Blob) {
  const image = new Image();
  image.src = URL.createObjectURL(blob);
  return new Promise<{ width: number; height: number; image: HTMLImageElement }>(
    (resolve, reject) => {
      image.onload = function () {
        resolve({
          width: image.width,
          height: image.height,
          image: image,
        });
      };
      image.onerror = function (err) {};
    },
  );
}

// 压缩图像为指定的分辨率大小
export async function compressImage({
  blob,
  image,
  width,
  height,
  quality = 0.8,
  format = 'image/jpeg',
}: {
  blob: Blob;
  image: HTMLImageElement;
  width: number;
  height: number;
  quality?: number;
  format?: string;
}): Promise<Blob> {
  // 创建Canvas
  const canvas = document.createElement('canvas');
  canvas.width = width;
  canvas.height = height;

  // 绘制图片
  const ctx = canvas.getContext('2d');

  return new Promise((resolve, reject) => {
    if (ctx) {
      ctx.fillStyle = 'white';
      ctx.fillRect(0, 0, canvas.width, canvas.height);
      // 计算图像在 canvas 上的位置和大小，保持图像不变形
      const imgWidth = image.naturalWidth;
      const imgHeight = image.naturalHeight;
      const aspectRatio = imgWidth / imgHeight;

      let drawWidth, drawHeight, drawX, drawY;

      if (aspectRatio > width / height) {
        drawWidth = width;
        drawHeight = width / aspectRatio;
        drawX = 0;
        drawY = (height - drawHeight) / 2;
      } else {
        drawWidth = height * aspectRatio;
        drawHeight = height;
        drawX = (width - drawWidth) / 2;
        drawY = 0;
      }

      // 绘制图像
      ctx.drawImage(image, drawX, drawY, drawWidth, drawHeight);

      // 转换为Blob（压缩质量可调）
      canvas.toBlob(
        (compressBlob) => {
          // blob为压缩后的文件，可用于上传
          if (compressBlob) {
            resolve(compressBlob);
          } else {
            resolve(blob);
          }
          resolve(blob);
          image.remove();
          canvas.remove();
        },
        format,
        quality,
      ); // 格式可选JPEG/PNG，质量0-1
    } else {
      resolve(blob);
      image.remove();
      canvas.remove();
    }
  });
}

// 保存文件
export async function saveTextFile(
  directoryHandle: FileSystemDirectoryHandle,
  text: string,
  fileName: string,
) {
  const fileHandle = await directoryHandle.getFileHandle(fileName, { create: true });
  const fileWriter = await fileHandle.createWritable();
  await fileWriter.write(text);
  await fileWriter.close();
}

// 获取图像的像素信息
export async function getPixelDataFromImage(imageData: string | Blob): Promise<ImageData> {
  if (typeof imageData === 'string') {
    const response = await fetch(imageData);
    imageData = await response.blob();
  }
  const bitmap = await createImageBitmap(imageData);

  const canvas = new OffscreenCanvas(bitmap.width, bitmap.height);
  const ctx = canvas.getContext('2d')!;

  ctx.drawImage(bitmap, 0, 0);

  return ctx.getImageData(0, 0, bitmap.width, bitmap.height);
}

// 根据远程的地址获取对应的 blob 对象
export async function getBlobByUrl(url: string) {
  const response = await fetch(url);
  return await response.blob();
}

// 实现一个并发控制函数
export function concurrentLimit<T>(tasks: (() => Promise<T>)[], limit = 6): Promise<T[]> {
  return new Promise((resolve, reject) => {
    let activeCount = 0; // 当前正在执行的任务数
    let currentIndex = 0; // 下一个要执行的任务的索引
    let resolvedCount = 0; // 已完成的任务数
    const results = new Array(tasks.length);
    let hasError = false;

    const next = () => {
      // 所有任务已完成，返回结果
      if (resolvedCount === tasks.length) {
        resolve(results);
        return;
      }

      // 当前没有存在错误或仍有任务待处理时，尝试启动新任务
      while (activeCount < limit && currentIndex < tasks.length && !hasError) {
        const taskIndex = currentIndex;
        const task = tasks[taskIndex];
        currentIndex++;
        activeCount++;

        task()
          .then((result) => {
            results[taskIndex] = result;
            resolvedCount++;
            activeCount--;
            next(); // 当前任务完成后触发下一个任务
          })
          .catch((error) => {
            hasError = true;
            reject(error); // 任一任务失败则整体拒绝
          });
      }
    };

    next(); // 初始调用以启动任务
  });
}

// 创建一个节流函数
export function throttle(fn: Function, delay: number) {
  let lastTime = 0;
  return function (this: any, ...args: any[]) {
    const now = Date.now();
    if (now - lastTime >= delay) {
      lastTime = now;
      fn.apply(this, args);
    }
  };
}

// 创建一个页面列表函数
export function getPageList(total: number, current: number, showPageCount: number) {
  if (total <= 0 || showPageCount <= 0) return [];

  current = Math.max(1, Math.min(current, total));

  let start = current - Math.floor((showPageCount - 1) / 2);
  let end = start + showPageCount - 1;

  // 调整溢出
  if (start < 1) {
    start = 1;
    end = Math.min(start + showPageCount - 1, total);
  }
  if (end > total) {
    end = total;
    start = Math.max(end - showPageCount + 1, 1);
  }

  const pages: (number | typeof Infinity)[] = [];

  // 前省略号
  if (start > 1) pages.push(-Infinity);

  // 核心页码
  for (let i = start; i <= end; i++) {
    pages.push(i);
  }

  // 后省略号
  if (end < total) pages.push(Infinity);

  return pages;
}

// 判断两个时间戳是否是同一天
export function isSameDay(timestamp1: number, timestamp2: number) {
  const date1 = new Date(timestamp1);
  const date2 = new Date(timestamp2);
  return (
    date1.getFullYear() === date2.getFullYear() &&
    date1.getMonth() === date2.getMonth() &&
    date1.getDate() === date2.getDate()
  );
}

// 获取一个文件的扩展名称
export function getFileExtension(filename: string): string {
  const match = filename.match(/\.([a-zA-Z0-9]+)$/);
  return match ? match[0].toLowerCase() : '';
}

// 判断两个数组的成员是否相同
export function areArraysEqualIgnoreOrder(arr1: string[], arr2: string[]) {
  // 首先检查长度是否相同
  if (arr1.length !== arr2.length) {
    return false;
  }

  // 创建一个对象来统计第一个数组的元素频率
  const frequency = {} as Record<string, number>;

  // 统计arr1中每个元素的出现次数
  for (const item of arr1) {
    frequency[item] = (frequency[item] || 0) + 1;
  }

  // 检查arr2中的元素是否与arr1匹配
  for (const item of arr2) {
    if (!frequency[item]) {
      return false;
    }
    frequency[item]--;
  }

  return true;
}

// 计算操作结果的颜色
export function getOperationResultColor(opeartionResult: string) {
  if (opeartionResult.startsWith('成功')) {
    return `hsl(var(--primary))`;
  }
  if (opeartionResult.startsWith('失败')) {
    return `hsl(var(--destructive))`;
  }
  if (opeartionResult.startsWith('不符合条件')) {
    return `#285af3`;
  }
  return '';
}

// 创建一个延迟处理的函数
export function delay(time: number) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve(true);
    }, time);
  });
}

// 限制文件名的大小
export function getLimitedFileName(fileName: string, maxLength = 20) {
  const dotIndex = fileName.lastIndexOf('.');
  const name = dotIndex !== -1 ? fileName.slice(0, dotIndex) : fileName;
  const ext = dotIndex !== -1 ? fileName.slice(dotIndex) : '';
  const limitedName = name.length > maxLength ? name.slice(0, maxLength) : name;
  return limitedName + ext;
}

// 计算获取视频的元信息
export async function getVideoMetadata(file: File) {
  return new Promise<{
    duration: number;
    width: number;
    height: number;
  }>((resolve, reject) => {
    const video = document.createElement('video');
    video.preload = 'metadata';
    const url = URL.createObjectURL(file);
    video.src = url;
    video.onloadedmetadata = () => {
      URL.revokeObjectURL(url);
      resolve({
        duration: video.duration,
        width: video.videoWidth,
        height: video.videoHeight,
      });
    };
    video.onerror = (error) => {
      URL.revokeObjectURL(url);
      reject(error);
    };
  });
}

// 链接地址
export function joinLink(baseUrl: string, path: string) {
  baseUrl = baseUrl.replace(/\/$/, '');
  path = path.replace(/^\//, '');
  return `${baseUrl}/${path}`;
}
